#! /usr/bin/env python
# Author: Diana Godfrey

PKG = 'languagememory'

from collections import defaultdict
import personObj
import nounObj
from nounObj import Noun
import random
import datetime
import urllib
import roslib; roslib.load_manifest(PKG)
import rospy
import re

from std_msgs.msg import String

class PersonMemory():

    newfood = False
    thisnewfood = "food"

    talkingPartner = personObj.PersonObject("nobody")

    friends = []
    #friendIndex = 0

    majors = {}
    ages = {}
    favs = defaultdict(dict)
    students = []
    personalFaveFoods = []
    personalLoathedFoods = []
    personalFavs = defaultdict(dict)
    personalRejects = defaultdict(dict)

    commentIntro = ["Hey, what's up. I'm Clarence.", "Hi, I'm Clarence.", "Hello. My name is Clarence."]
    commentName = ["What's your name?", "And you are ... ?", "Who are you?"]
    commentHi = ["Oh hi, %s.", "Hey %s, it's good to see you.", "Howdy, %s."]
    commentOldFriend = ["Hi, %s, long time no see!", "Oh, I'm glad you didn't leave yet, %s", "Hey, %s, you forget something?"]    
    commentAskMajor = ["What are you majoring in?", "So, what's your major?", "What's your field of study?"]
    commentMajor = ["Fascinating. %s also is majoring in %s.",
    "Oh cool, %s is studying %s too.",
    "Must be a popular program because %s also has %s as a major."]
    commentNewMajor = ["%s will make you a ton of money someday.", "Good choice. The future is in %s.", "%s? I would have thought you were more the lawyerly type."]    
    commentAge = ["If you don't mind my asking, %s, how old are you?", "So, %s, how old are you?",
    "What's your age, %s?"]
    commentAgeUnder = ["How interesting. Today I've met %d %s the age of %d.",
    "So far, %d of my new friends are %s the age of %d.",
    "You're number %d in the people I've met today who are %s the age of %d."]
    commentAgeOver = ["Already today I've met %d people %s %d.",
    "There's %d of you %s %d. You look like the youngest.",
    "Hm. I didn't realize there were as many as %d people here %s %d."]
    commentAgeSame = ["Freaky! %d of my new friends are %d!",
    "I think it's auspicious that %d of you are exactly %d.", "I have %d other friends who are also %d."]
    commentAgeOther = ["Oh cool, you were born around %d."]
    commentNewFood = ["I'll have to try %s sometime. Thanks for the recommendation.", "I must not get out much, because I've never heard of %s.", "%s sounds kind of good, even though I have no idea what it tastes like."]    
    commentFoodLike = ["%s, I LOVE %s!", "%s, I totally agree. %s is delicious.",
    "%s, I didn't know you liked %s too! Yum."]
    commentFoodLoath = ["Really. Because no offense, %s, but I don't really like %s.",
    "I want to be diplomatic, %s, but I don't care for %s at all. Maybe with a little salsa.",
    "Ew! Ahem, yes, %s, I hear %s is well-liked in certain circles."]
    commentFoodSame = ["I'll be darned, %s likes %s too.", "You probably eat out with %s a lot. %s is a mutual favorite.", "Hm, %s just told me %s is a preferred food."]
    commentWeather = ["Nice outfit. It's %s outside right now.",
    "%s right now -- I love this weather!", "The weather right now is %s, in case you were wondering."]
    commentGoAway = ["I've actually exhausted my Q & A repertoire with you, so go ahead and step aside.", "Let's chat later, K? I don't like to brag, but a lot of people want to be my friend right now.", "You'll be first on my list when I figure out some new questions to ask. Buh-bye."]    
    commentAskFriend = [ "Does anyone else want to chat?", "Is there someone else who wants to be my friend?",
    "Step right up, guys, I'm here to be your friend."]


    def __init__(self):
        self.data = []
        self.personalFaveFoods = [Noun("pizza"), Noun("Indian food"), Noun("walnuts"), Noun("chocolate"), Noun("french toast"), Noun("potato soup"), Noun("peanut butter and jelly"), Noun("marshmallows"), Noun("blue spheres with salt"), Noun("WD-40")]
        self.personalLoathedFoods = [Noun("hamburgers"), Noun("bananas"), Noun("kittens"), Noun("nachos"), Noun("spinach"), Noun("fried cucumbers"),
            Noun("battery acid"), Noun("donuts"), Noun("macadamia nuts"), Noun("eggs")]
        self.personalFavs["food"] = self.personalFaveFoods
        self.personalRejects["food"] = self.personalLoathedFoods
        self.tts_pub = rospy.Publisher("tts", String)

    def askFriend(self):
        ranfriend = self.getRan(0, 2)
        return self.commentAskFriend[ranfriend]

    def introduce(self, name):
        self.newfood = False
        if name:
            ranGoAway = self.getRan(0, 2)
            stuff =  "Hi, %s! It's been too long!"%name + "                " + self.commentGoAway[ranGoAway] + "                            " + self.askFriend()
            return stuff
        else:
            ranintro = self.getRan(0, 2)        #my name is Clarence
            ranname = self.getRan(0, 2)         #what's your name       
            return self.commentIntro[ranintro] + "\n" + self.commentName[ranname]

    def callMakeFriend(self, name):
        ranHi = self.getRan(0, 2)
        isoldfriend = (self.makeFriend(name))
        if isoldfriend == True:
            ranOldFriend = self.getRan(0, 2)
            ranGoAway = self.getRan(0, 2)
            return self.commentOldFriend[ranOldFriend] % (name) + "           " + self.commentGoAway[ranGoAway] + "                            " + self.askFriend()
        else:
            return self.commentHi[ranHi] % name
#	 	    if name == "paul":
#			    return "Oh hi, %s! Your class has been working so hard this semester."
#		    else:
 #               return self.commentHi[ranHi] % name

    def makeFriend(self, name):
        if name in self.friends:
            oldFriend = personObj.getPerson(name)
            self.defineTalker(oldFriend)
            return True
        else:
            newFriend = personObj.PersonObject(name)
            self.friends.append(newFriend.getName())            
            self.defineTalker(newFriend)
            return False

    def defineTalker(self, person):
        print "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Your new talkingPartner is " + person.getName()
        self.talkingPartner = person

    def askMajor(self):
        ranMajor = self.getRan(0, 2)
        return self.commentAskMajor[ranMajor]

    def respondMajor(self, major):
        self.talkingPartner.giveMajor(major)
        match = self.matchMajor(major)
        rancomment = self.getRan(0, 2)
        self.addMajor(major, self.talkingPartner)
        if (match[0] != None):
           ranstud = self.getRan(0, match[1]-1)
           return self.commentMajor[rancomment] % (match[0][ranstud].getName(), major)
        return self.commentNewMajor[rancomment] % major

    def addMajor(self, major, person):
        if self.majors.has_key(major):
            self.majors[major].append(person)
        else:
            self.majors[major] = [person]
        students = []
        if self.majors.has_key(major):
            students = self.majors[major]
            return [students, len(students)]
        return [None]

    def matchMajor(self, major):
        students = []
        if self.majors.has_key(major):
            students = self.majors[major]
            return [students, len(students)]
        return [None]

    def askAge(self):
        ranage = self.getRan(0, 2)
        age = raw_input ("\n" + self.commentAge[ranage] % self.talkingPartner.getName() + "\n")
        self.talkingPartner.giveAge(age)
        self.addAge(age, self.talkingPartner)

    def respondAge(self, age):	
	age = int(age)
	ranchoice = self.getRan(0, 99)
	if ranchoice < 25:
            students = self.matchAge(self.getVal(age, "ceiling"), "under")
            if (students[0] != 0):
                ranunder = self.getRan(0, 2)
                return(self.commentAgeUnder[ranunder]% (students[0], students[1], students[2]))
        elif ranchoice < 50:
            students = self.matchAge(self.getVal(age, "floor"), "over")
            if (students[0] != 0):
                ranover = self.getRan(0, 2)
                return(self.commentAgeOver[ranover]%(students[0], students[1], students[2]))
        elif ranchoice < 70:
            students = self.matchAge(age, "same")
            if (students[0] > 1):
                ransame = self.getRan(0, 2)
                return(self.commentAgeSame[ransame]% (students[0], students[2]))
        else:
           return(self.commentAgeOther[0]%self.getBirthYear(age))

    def addAge(self, age, person):
        if self.ages.has_key(age):
            self.ages[age].append(person)
        else:
            self.ages[age] = [person]

    def matchAge(self, age, relation):
        limit = age
        if relation is "under":
            youngsters = 0
            for k in self.ages:
              if (int(k) < limit):
                youngsters += len(self.ages[k])
            return [youngsters, relation, age]
        if relation is "over":
            oldsters = 0
            for k in self.ages:
        	if (int(k) > limit):
                	oldsters += len(self.ages[k])
            		return [oldsters, relation, age]
        if relation is "same":
            samesters = 0
            for k in self.ages:
                if (int(k) == limit):
                    samesters += len(self.ages[k])
            return [samesters, relation, age]

    def askFood(self):
        ranfavefood = self.getRan(0, 9)
        return "I like %s. What is your favorite food?"%self.personalFaveFoods[ranfavefood].getName()

    def respondFood(self, foodkind):
        student = self.matchFav("food", foodkind)
        self.talkingPartner.giveFav("food", foodkind)
        if len(student) > 0:
            ranfood = self.getRan(0, len(student)-1)
            ranfoodsameindex = self.getRan(0, 2)
            self.addFav("food", foodkind, self.talkingPartner)
            return self.commentFoodSame[ranfoodsameindex] % (student[ranfood].getName(), foodkind)
        else:
            opinion = False
            ranfoodindex = self.getRan(0, 2)
            self.addFav("food", foodkind, self.talkingPartner)
            for item in self.personalFavs["food"]:
                if item.getName() == foodkind:
                    opinion = True
                    return "\n" + self.commentFoodLike[ranfoodindex] % (self.talkingPartner.getName(), foodkind) + "\n"
            if opinion != True:
                for item in self.personalRejects["food"]:
                    if item.getName() == foodkind:
                        opinion = True
                        return "\n" + self.commentFoodLoath[ranfoodindex] % (self.talkingPartner.getName(), foodkind) + "\n"
            if opinion != True:
                self.newfood = True
               # self.addFav("food", foodkind, self.talkingPartner)
                return "\n" + self.commentNewFood[ranfoodindex] % foodkind + "\n"
        self.talkWeather()

    def talkFood(self):
        if (self.newfood):
            self.thisnewfood = self.talkingPartner.getFav("food")
            return "Say, %s, I've been thinking. Do you think I might like %s?" % (self.talkingPartner.getName(), self.thisnewfood)
           # answer = raw_input("\nSay, %s, I've been thinking. Do you think I might like %s?\n" % (self.talkingPartner.getName(), thisnewfood))
            #if (answer == ("yes" or "maybe" or "you might" or "you may" or "possibly")):
             #   return "OK, I'll try it. But if I don't like it, we're going to have words."
              #  self.addFood(thisnewfood)
               # self.askFriend()
            #else:
             #   return "OK, well, enjoy your %s and I'll see you later!" % thisnewfood
        else:
            return "Hey, %s, what is a food you think I'd like?" % self.talkingPartner.getName()
            #foodanswer = raw_input ("\nHey, %s, is there a food you think I'd like?\n" % self.talkingPartner.getName())
           # if self.checkExistenceFood(foodanswer) == False:
            #    confirm = raw_input ("Is %s a food?\n" % foodanswer)
             #   if confirm == ("no" or "not exactly" or "not really"):
              #      foodanswer2 = raw_input ("Well, tell me a food, please.\n")
               #     if self.checkExistenceFood(foodanswer2) == False:
                #        confirm2 = raw_input ("Now, is %s a food?\n" % foodanswer2)
                 #       if confirm2 == ("no" or "not exactly" or "not really"):
                  #          return "K, let's talk about food some other time. See ya."
                   #         self.askFriend()
                    #    else:
                     #       return "OK, thanks, %s. I'll try %s!\n" % (self.talkingPartner.getName(), foodanswer2)
                      #      self.addFood(foodanswer2)
#                    else:
#                        "Great, %s, I'll try %s. Thank you for broadening my horizons!\n" % (self.talkingPartner.getName(), foodanswer)
#                        self.addFood(foodanswer2)
               # else:
                #    return "Well, it won't hurt to try %s. Thanks, %s!\n" %(foodanswer, self.talkingPartner.getName())
                 #   self.addFood(foodanswer)
                    
    def commentFood(self, answer):
        if answer == "yes":
            return self.addFood(self.thisnewfood)
           # return "OK, I'll try it. But if I don't like it, we're going to have words."
        elif answer == "no":
            return "OK, well, enjoy your %s and I'll see you later!" % self.thisnewfood
        else:
            return self.checkExistenceFood(answer)
                                           
    def checkExistenceFood(self, food):
        exist = False
        for item in self.personalFavs["food"]:
                if item.getName() == food:
                    exist == True
                    return "Wait, %s is already on my personal list of favorites! Thanks!" % food  
        for item in self.personalRejects["food"]:
            if item.getName() == food:
                exist = True
                return "Wait, no, no, no. I can't stand %s. I thought you knew me better than that, but we're good." % food    
        else:
            return self.addFood(food)
            
    def addFood(self, food):
        likesFood = self.matchFav("food", food)
        if len(likesFood) > 1:
            print likesFood
            ranfood = self.getRan(0, len(likesFood)-2)
            self.personalFavs["food"].append(Noun(str(food)))
            return "You know, %s likes %s too! I'm happy to join the club of %s fans." % (likesFood[ranfood].getName(), food, food)
        else:
            self.personalFavs["food"].append(Noun(str(food)))
            return "Great, %s, I'll try %s. Thank you for broadening my horizons!\n" % (self.talkingPartner.getName(), food)
        

    def talkWeather(self):
        ranweather = self.getRan(0, 2)
        return self.commentWeather[ranweather]%self.getWeather()

    def addFav(self, cat, kind, person):
        if self.favs.has_key(cat) & self.favs[cat].has_key(kind):
                self.favs[cat][kind].append(person)
        else:
            self.favs[cat][kind] = [person]

    def matchFav(self, cat, kind):
        students = []
        if self.favs.has_key(cat):
            if self.favs[cat].has_key(kind):
                students = self.favs[cat][kind]
        return students

    def printMajors(self):
        for k in iter(self.majors):
            print "%s:" % k,
            students = self.majors[k]
            for s in students:
                print s.getName(),
            print "\n"

    def printFriends(self):
        for k in self.friends:
            print self.friends[k]

    def getRan(self, start, stop):
        return random.randint(start, stop)

    def getVal(self, num, distance):
        if distance is "ceiling":
            return (10 + 10 * (int(num)/10))
        elif distance is "floor":
            return 10 * (int(num)/10)

    def getBirthYear(self, age):
        return (datetime.datetime.now().year - int(age))

    def getWeather(self, zipcode = 85719):
        if zipcode != 0:
            from xml.dom import minidom
            WEATHER_URL = 'http://xml.weather.yahoo.com/forecastrss?p=%s'
            WEATHER_NS = 'http://xml.weather.yahoo.com/ns/rss/1.0'
            url = WEATHER_URL % zipcode
            dom = minidom.parse(urllib.urlopen(url))
            ycondition = dom.getElementsByTagNameNS(WEATHER_NS, 'condition')[0]
            weatherReport = ycondition.getAttribute('temp') + ' and ' + ycondition.getAttribute('text')
        else:
            weatherReport = "No zip code set."
        return str(weatherReport)

    def end(self):
        return " Goodbye."

#
#    baseUrl = "http://ajax.googleapis.com/ajax/services/language/translate"
#
#    def translate(self, text,src='fr', to='en'):
##    A Python Wrapper for Google AJAX Language API:
##    * Uses Google Language Detection, in cases source language is not provided with the source text
##    * Splits up text if it's longer then 4500 characters, as a limit put up by the API
#        params = ({'langpair': '%s|%s' % (src, to),
#             'v': '1.0'
#             })
#        retText=''
#        params['q'] = text
#        resp = simplejson.load(urllib.urlopen('%s' % self.baseUrl, data = urllib.urlencode(params)))
#        try:
#                retText = resp['responseData']['translatedText']
#        except:
#                raise
#        return retText


#    def test(self, message):
#        print message
#        text = message
#        retText = self.translate(text)
#        print retText

if __name__ == '__main__':
    mem = PersonMemory()
    count = 34
    while (count > 0):
#        mem.test("aimer")
        mem.introduce("Diana")
        mem.askMajor()
        mem.askAge()
        mem.askFood()
        mem.talkWeather()
        count = count - 1
        mem.end()


